package net.csdn.business.notify.api.service.impl;

import cn.hutool.core.util.IdUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import lombok.extern.slf4j.Slf4j;
import net.csdn.business.notify.api.service.INotifyAnnounceService;
import net.csdn.business.notify.common.config.AsyncThreadPoolConfig;
import net.csdn.business.notify.common.enums.ResultCodeEnum;
import net.csdn.business.notify.common.exception.BusinessException;
import net.csdn.business.notify.common.mapper.NotifyAnnounceMapper;
import net.csdn.business.notify.common.mapper.NotifyAnnounceUserMapper;
import net.csdn.business.notify.common.model.dto.NewNotifyAnnounceDTO;
import net.csdn.business.notify.common.model.dto.UpdateNotifyAnnounceDTO;
import net.csdn.business.notify.common.model.entity.NotifyAnnounce;
import net.csdn.business.notify.common.model.entity.NotifyAnnounceUser;
import net.csdn.business.notify.common.model.query.NotifyAnnounceQuery;
import net.csdn.business.notify.common.model.vo.NotifyAnnounceVO;
import net.csdn.business.notify.common.model.vo.UserAnnounceVO;
import net.csdn.business.notify.common.model.vo.UserInfoVO;
import net.csdn.business.notify.feign.SystemFeignClient;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.util.*;
import java.util.concurrent.Future;


/**
 * 通知中心-系统公告Service业务层处理
 * 
 * @author ruoyi
 * @date 2023-11-27
 */
@Slf4j
@Service
public class NotifyAnnounceServiceImpl extends ServiceImpl<NotifyAnnounceMapper, NotifyAnnounce> implements INotifyAnnounceService
{


    @Autowired
    private NotifyAnnounceUserMapper notifyAnnounceUserMapper;

    @Resource(name= AsyncThreadPoolConfig.ASYNC_EXECUTOR_POOL_NAME)
    private ThreadPoolTaskExecutor asyncExecutor;

    @Autowired
    private SystemFeignClient userFeignClient;

    /**
     * 分页查询通知中心-系统公告列表
     *
     * @param query 通知中心-系统公告
     * @return 通知中心-系统公告
     */
    @Override
    public Page<NotifyAnnounceVO> findPageList(NotifyAnnounceQuery query) {
        //获得Page对象
        Page<NotifyAnnounceVO> page = query.getPage();
        List<NotifyAnnounceVO> pageList=baseMapper.findPageList(page,query);
        if(pageList!=null&&pageList.size()>0){
            List<String> userIds=new ArrayList<>();
            pageList.stream().forEach(notifyAnnounceVO->{
                String createdBy=notifyAnnounceVO.getCreatedBy();
                userIds.add(createdBy);
            });
            try {
                Future<Map<String, UserInfoVO>> taskA =asyncExecutor.submit(()->{
                    //批量查询用户信息
                    Map<String, UserInfoVO> userInfoMap=new HashMap<>();
                    try {
                        userInfoMap=userFeignClient.batchQuery(userIds);
                    }catch (Exception e){
                        log.info("query remote user info error");
                    }
                    return userInfoMap;
                });
                Map<String, UserInfoVO> finalUserInfoMap = taskA.get();
                pageList.stream().parallel().forEach(notifyAnnounceVO->{
                    String createdBy=notifyAnnounceVO.getCreatedBy();
                    UserInfoVO createdInfo = finalUserInfoMap.get(createdBy);
                    if(createdInfo!=null){
                        notifyAnnounceVO.setCreatedByUserName(createdInfo.getUsername());
                        notifyAnnounceVO.setCreatedByUserPhoto(createdInfo.getPhoto());
                    }
                });
            }catch (Exception e){
                e.printStackTrace();
            }
        }
        page.setRecords(pageList);
        return page;
    }

    /**
     * 根据id查询通知中心-系统公告
     * 
     * @param id 通知中心-系统公告主键
     * @return 通知中心-系统公告
     */
    @Override
    public NotifyAnnounceVO selectNotifyAnnounceById(String id)
    {
        NotifyAnnounceVO result=baseMapper.selectNotifyAnnounceById(id);
        if(result==null){
            throw new BusinessException(ResultCodeEnum.PARAMETER_ERROR_CUSTOM,"id");
        }
        return result;
    }

    /**
     * 查询通知中心-系统公告列表
     * 
     * @param query 通知中心-系统公告
     * @return 通知中心-系统公告
     */
    @Override
    public List<NotifyAnnounceVO> selectNotifyAnnounceList(NotifyAnnounceQuery query)
    {
        return baseMapper.selectNotifyAnnounceList(query);
    }

    /**
     * 新增通知中心-系统公告
     *
     * @param params 通知中心-系统公告
     * @return 结果
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public Integer insertNotifyAnnounce(NewNotifyAnnounceDTO params)
    {
        Boolean isAll=params.getIsAll();
        List<String> receiverIds=params.getReceiverIds();
        if(!isAll&&(receiverIds==null||receiverIds.size()==0)){
            throw new BusinessException(ResultCodeEnum.NOTIFY_ANNOUNCE_RECEIVER_ERROR);
        }
        String announceId=IdUtil.fastSimpleUUID();
        NotifyAnnounce notifyAnnounce=new NotifyAnnounce();
        BeanUtils.copyProperties(params,notifyAnnounce);
        notifyAnnounce.setObjectId(announceId);
        notifyAnnounce.setCreatedBy(params.getCurUserId());
        int result=baseMapper.insert(notifyAnnounce);
        //如果插入成功，不为全员发送，则记录特定接收人的
        if(result>0&!isAll){
            List<NotifyAnnounceUser> announceUsers=new ArrayList<>();
            for (String userId:receiverIds){
                NotifyAnnounceUser notifyAnnounceUser=new NotifyAnnounceUser();
                notifyAnnounceUser.setObjectId(IdUtil.fastSimpleUUID());
                notifyAnnounceUser.setAnnounceId(announceId);
                notifyAnnounceUser.setReceiverId(userId);
                notifyAnnounceUser.setReadState(0);
                announceUsers.add(notifyAnnounceUser);
            }
            notifyAnnounceUserMapper.insertBatch(announceUsers);
        }
        return result;
    }

    /**
     * 修改通知中心-系统公告
     *
     * @param params 通知中心-系统公告
     * @return 结果
     */
    @Override
    public Integer updateNotifyAnnounce(UpdateNotifyAnnounceDTO params)
    {
        NotifyAnnounceVO result=baseMapper.selectNotifyAnnounceById(params.getId());
        if(result==null){
            throw new BusinessException(ResultCodeEnum.PARAMETER_ERROR_CUSTOM,"id");
        }
        LambdaUpdateWrapper<NotifyAnnounce> updateWrapper = new UpdateWrapper<NotifyAnnounce>().lambda();
        updateWrapper.eq(NotifyAnnounce::getObjectId, params.getId());
        NotifyAnnounce notifyAnnounce=new NotifyAnnounce();
        BeanUtils.copyProperties(params,notifyAnnounce);
        notifyAnnounce.setLastModifiedBy(params.getCurUserId());
        return baseMapper.update(notifyAnnounce,updateWrapper);
    }

    /**
     * 删除通知中心-系统公告信息
     * 
     * @param id 通知中心-系统公告主键
     * @return 结果
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public Integer deleteNotifyAnnounceById(String id)
    {
        NotifyAnnounceVO notifyAnnounceVO=baseMapper.selectNotifyAnnounceById(id);
        if(notifyAnnounceVO==null){
            throw new BusinessException(ResultCodeEnum.PARAMETER_ERROR_CUSTOM,"id");
        }
        int result=baseMapper.deleteNotifyAnnounceById(id);
        if(result>0){
            //删除关联数据
            notifyAnnounceUserMapper.deleteNotifyAnnounceUser(id);
        }
        return result;
    }

    @Override
    public Page<UserAnnounceVO> userAnnouncePage(NotifyAnnounceQuery query) {
        String currUserId=query.getCurrUserId();
        if(StringUtils.isBlank(currUserId)){
            throw new BusinessException(ResultCodeEnum.PARAMETER_ERROR_CUSTOM,"currUserId");
        }
        //获得Page对象
        Page<UserAnnounceVO> page = query.getPage();
        List<UserAnnounceVO> pageList=baseMapper.userAnnouncePage(page,query);
        if(pageList!=null&&pageList.size()>0){
            List<String> userIds=new ArrayList<>();
            pageList.stream().forEach(announceVO->{
                String createdBy=announceVO.getCreatedBy();
                userIds.add(createdBy);
            });
            userIds.add(currUserId);
            try {
                Future<Map<String, UserInfoVO>> taskA =asyncExecutor.submit(()->{
                    //批量查询用户信息
                    Map<String, UserInfoVO> userInfoMap=new HashMap<>();
                    try {
                        userInfoMap=userFeignClient.batchQuery(userIds);
                    }catch (Exception e){
                        log.info("query remote user info error");
                    }
                    return userInfoMap;
                });
                Map<String, UserInfoVO> finalUserInfoMap = taskA.get();
                pageList.stream().parallel().forEach(announceVO->{
                    String createdBy=announceVO.getCreatedBy();
                    UserInfoVO createInfo = finalUserInfoMap.get(createdBy);
                    if(createInfo!=null){
                        announceVO.setCreatedByUserName(createInfo.getUsername());
                        announceVO.setCreatedByUserPhoto(createInfo.getPhoto());
                    }
                });
            }catch (Exception e){
                e.printStackTrace();
            }
        }
        page.setRecords(pageList);
        return page;
    }

    @Override
    public UserAnnounceVO userAnnounceDetail(NotifyAnnounceQuery query) {
        String id=query.getId();
        if(StringUtils.isBlank(id)){
            throw new BusinessException(ResultCodeEnum.PARAMETER_ERROR_CUSTOM,"id");
        }
        String currUserId=query.getCurrUserId();
        if(StringUtils.isBlank(currUserId)){
            throw new BusinessException(ResultCodeEnum.PARAMETER_ERROR_CUSTOM,"currUserId");
        }
        UserAnnounceVO userAnnounceVO=baseMapper.userAnnounceDetail(query);
        if(userAnnounceVO==null){
            throw new BusinessException(ResultCodeEnum.PARAMETER_ERROR_CUSTOM,"id");
        }
        //异步查询是否已读，如果未读，则插入已读记录
        asyncExecutor.execute(()->{
            LambdaQueryWrapper<NotifyAnnounceUser> queryWrapper = new LambdaQueryWrapper<>();
            queryWrapper.eq(NotifyAnnounceUser::getAnnounceId, id);
            queryWrapper.eq(NotifyAnnounceUser::getReceiverId,currUserId);
            NotifyAnnounceUser record=notifyAnnounceUserMapper.selectOne(queryWrapper);
            if(record==null){
                NotifyAnnounceUser notifyAnnounceUser=new NotifyAnnounceUser();
                notifyAnnounceUser.setObjectId(IdUtil.fastSimpleUUID());
                notifyAnnounceUser.setAnnounceId(id);
                notifyAnnounceUser.setReceiverId(currUserId);
                notifyAnnounceUser.setReadState(1);
                notifyAnnounceUser.setReadDate(new Date());
                notifyAnnounceUserMapper.insert(notifyAnnounceUser);
            }
        });
        return userAnnounceVO;
    }

    @Override
    public int getUnReadCount(String currUserId) {
        return baseMapper.getUnReadCount(currUserId);
    }

}
